home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / ifconf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-25  |  13.8 KB  |  486 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. /*******************************************************************/
  28. /*                                                                 */
  29. /*  INET checking for cfengine                                     */
  30. /*                                                                 */
  31. /*  This is based on the action of "ifconfig" for IP protocols     */
  32. /*  It assumes that we are on the internet and uses ioctl to get   */
  33. /*  the necessary info from the device. Sanity checking is done... */
  34. /*                                                                 */
  35. /* Sockets are very poorly documented. The basic socket adress     */
  36. /* struct sockaddr is a generic type. Specific socket addresses    */
  37. /* must be specified depending on the family or protocol being     */
  38. /* used. e.g. if you're using the internet inet protocol, then     */
  39. /* the fmaily is AF_INT and the socket address type is sockadr_in  */
  40. /* Although it is not obvious, the documentation assures us that   */
  41. /* we can cast a pointer of one type into a pointer of the other:  */
  42. /*                                                                 */
  43. /* Here's an example                                               */
  44. /*                                                                 */
  45. /*   #include <netinet/in.h>                                       */
  46. /*                                                                 */
  47. /*        struct in_addr adr;                                      */
  48. /* e.g.   adr.s_addr = inet_addr("129.240.22.34");                 */
  49. /*        printf("addr is %s\n",inet_ntoa(adr));                   */
  50. /*                                                                 */
  51. /*                                                                 */
  52. /* We have to do the following in order to convert                 */
  53. /* a sockaddr struct into a sockaddr_in struct required by the     */
  54. /* ifreq struct!! These calls have no right to work, but somehow   */
  55. /* they do!                                                        */
  56. /*                                                                 */
  57. /* struct sockaddr_in sin;                                         */
  58. /* sin.sin_addr.s_addr = inet_addr("129.240.22.34");               */
  59. /*                                                                 */
  60. /* IFR.ifr_addr = *((struct sockaddr *) &sin);                     */
  61. /*                                                                 */
  62. /* sin = *(struct sockaddr_in *) &IFR.ifr_addr;                    */
  63. /*                                                                 */
  64. /* printf("IP address: %s\n",inet_ntoa(sin.sin_addr));             */
  65. /*                                                                 */
  66. /*******************************************************************/
  67.  
  68. #define INET
  69. #include "cf.defs.h"
  70. #include "cf.extern.h"
  71.  
  72. #if !defined(NT) && !defined(IRIX)
  73.  
  74. /* IRIX makes the routing stuff obsolete unless we do this */
  75. # undef sgi
  76.  
  77. struct ifreq IFR;
  78.  
  79. char VNUMBROADCAST[256];
  80.  
  81. # define cfproto 0
  82.  
  83. # ifndef IPPROTO_IP     /* Old boxes, hpux 7 etc */
  84. #  define IPPROTO_IP 0
  85. # endif
  86.  
  87. # ifndef SIOCSIFBRDADDR
  88. #  define SIOCSIFBRDADDR  SIOCGIFBRDADDR
  89. # endif
  90.  
  91. /*******************************************************************/
  92.  
  93. IfConf (vifdev,vnetmask,vbroadcast)
  94.  
  95. char *vifdev,*vnetmask, *vbroadcast;
  96.  
  97. { int sk, flags, metric, isnotsane = false;
  98.  
  99.  
  100. Verbose("Assumed interface name: %s %s %s\n",vifdev,vnetmask,vbroadcast);
  101.  
  102. if (getuid() != 0)                            
  103.    {
  104.    printf("%s: Only root can configure the net interface.\n",VPREFIX);
  105.    return;
  106.    }
  107.  
  108. if (vnetmask[0] == '\0')
  109.    {
  110.    CfLog(cferror,"Program does not define a subnetmask","");
  111.    return;
  112.    }
  113.  
  114. if (vbroadcast[0] == '\0')
  115.    {
  116.    CfLog(cferror,"Program does not define a broadcast mode for this host","");
  117.    return;
  118.    }
  119.  
  120.  
  121. strcpy(IFR.ifr_name,vifdev);
  122. IFR.ifr_addr.sa_family = AF_INET;
  123.  
  124. if ((sk = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP)) == -1)
  125.    {
  126.    CfLog(cferror,"","socket");
  127.    FatalError("Error in IfConfig()");
  128.    }
  129.  
  130. if (ioctl(sk,SIOCGIFFLAGS, (caddr_t) &IFR) == -1)   /* Get the device status flags */
  131.    {
  132.    CfLog(cferror,"No such network device","ioctl");
  133.    return;
  134.    }
  135.  
  136. flags = IFR.ifr_flags;
  137. strcpy(IFR.ifr_name,vifdev);                   /* copy this each time */
  138.  
  139. if (ioctl(sk,SIOCGIFMETRIC, (caddr_t) &IFR) == -1)   /* Get the routing priority */
  140.    {
  141.    CfLog(cferror,"","ioctl");
  142.    FatalError("Software error: error getting metric");
  143.    }
  144.  
  145. metric = IFR.ifr_metric;
  146.  
  147. isnotsane = GetIfStatus(sk,vifdev,vnetmask,vbroadcast);
  148.  
  149. if (! DONTDO && isnotsane)
  150.    {
  151.    SetIfStatus(sk,vifdev,vnetmask,vbroadcast);
  152.    GetIfStatus(sk,vifdev,vnetmask,vbroadcast);
  153.    }
  154.  
  155. close(sk);
  156. }
  157.  
  158.  
  159. /*******************************************************************/
  160.  
  161. GetIfStatus(sk,vifdev,vnetmask,vbroadcast)
  162.  
  163. int sk;
  164. char *vifdev,*vnetmask,*vbroadcast;
  165.  
  166. { struct sockaddr_in *sin;
  167.   struct sockaddr_in netmask;
  168.   int insane = false;
  169.   struct hostent *hp;
  170.   struct in_addr inaddr;
  171.  
  172. Verbose("Checking interface status...\n");
  173.   
  174. if ((hp = gethostbyname(VSYSNAME.nodename)) == NULL)
  175.    {
  176.    CfLog(cferror,"","gethostbyname");
  177.    return false;
  178.    }
  179. else
  180.    {
  181.    bcopy(hp->h_addr,&inaddr, hp->h_length);
  182.    Verbose("Address given by nameserver: %s\n",inet_ntoa(inaddr));
  183.    }
  184.  
  185. strcpy(IFR.ifr_name,vifdev);
  186.  
  187. if (ioctl(sk,SIOCGIFADDR, (caddr_t) &IFR) == -1)   /* Get the device status flags */
  188.    {
  189.    return false;
  190.    }
  191.  
  192. sin = (struct sockaddr_in *) &IFR.ifr_addr;
  193.  
  194.  
  195. if (strcmp((char *)inet_ntoa(*(struct in_addr *)(hp->h_addr)),(char *)inet_ntoa(sin->sin_addr)) != 0)
  196.    {
  197.    CfLog(cferror,"This machine is configured with an address which differs from\n","");
  198.    CfLog(cferror,"the nameserver's information! (Insane!)\n","");
  199.    CfLog(cferror,"Don't quite know what to do...\n","");
  200.    insane = true;
  201.    }
  202.  
  203. if (ioctl(sk,SIOCGIFNETMASK, (caddr_t) &IFR) == -1) 
  204.    {
  205.    return false;
  206.    }
  207.  
  208. netmask.sin_addr = ((struct sockaddr_in *) &IFR.ifr_addr)->sin_addr;
  209.  
  210. Verbose("Found netmask: %s\n",inet_ntoa(netmask.sin_addr));
  211.  
  212. strcpy(VBUFF,inet_ntoa(netmask.sin_addr));
  213.  
  214. if (strcmp(VBUFF,vnetmask))
  215.    {
  216.    CfLog(cferror,"The netmask is incorrectly configured, resetting...\n","");
  217.    insane = true;
  218.    }
  219.  
  220. if (ioctl(sk,SIOCGIFBRDADDR, (caddr_t) &IFR) == -1) 
  221.    {
  222.    return false;
  223.    }
  224.  
  225. sin = (struct sockaddr_in *) &IFR.ifr_addr;
  226. strcpy(VBUFF,inet_ntoa(sin->sin_addr));
  227.  
  228. Verbose("Found broadcast address: %s\n",inet_ntoa(sin->sin_addr));
  229.  
  230. GetBroadcastAddr(inet_ntoa(inaddr),vifdev,vnetmask,vbroadcast);
  231.  
  232. if (strcmp(VBUFF,VNUMBROADCAST) != 0)
  233.    {
  234.    sprintf(OUTPUT,"Broadcast address was %s (should be bit-type %s)\n",VBUFF,vbroadcast);
  235.    CfLog(cferror,OUTPUT,"");
  236.    insane = true;
  237.    }
  238.  
  239. return(insane);
  240. }
  241.  
  242. /*******************************************************************/
  243.  
  244. SetIfStatus(sk,vifdev,vnetmask,vbroadcast)
  245.  
  246. int sk;
  247. char *vifdev,*vnetmask, *vbroadcast;
  248.  
  249. { struct sockaddr_in *sin;
  250.   struct sockaddr_in netmask, broadcast;
  251.  
  252.    /*********************************
  253.  
  254.    Don't try to set the address yet...
  255.  
  256.     if (ioctl(sk,SIOCSIFADDR, (caddr_t) &IFR) == -1) 
  257.       {
  258.       perror ("Can't set IP address");
  259.       return;
  260.       } 
  261.  
  262.    **********************************/
  263.  
  264. /* set netmask */
  265.  
  266. Verbose("Resetting interface...\n");
  267. strcpy(IFR.ifr_name,vifdev);
  268. netmask.sin_addr.s_addr = inet_network(vnetmask);
  269. IFR.ifr_addr = *((struct sockaddr *) &netmask);
  270. sin = (struct sockaddr_in *) &IFR.ifr_addr;
  271.  
  272. if (ioctl(sk,SIOCSIFNETMASK, (caddr_t) &IFR) < 0) 
  273.    {
  274.    CfLog(cferror,"Permission to reconfigure netmask denied.\n","ioctl");
  275.    }
  276. else
  277.    {
  278.    sprintf(OUTPUT,"Set Netmask to: %s\n",inet_ntoa(netmask.sin_addr));
  279.    CfLog(cfinform,OUTPUT,"");
  280.    }
  281.  
  282. /* broadcast addr */
  283.  
  284. strcpy(IFR.ifr_name,vifdev);
  285. broadcast.sin_addr.s_addr = inet_addr(VNUMBROADCAST);
  286. IFR.ifr_addr = *((struct sockaddr *) &broadcast);
  287. sin = (struct sockaddr_in *) &IFR.ifr_addr;
  288.  
  289. Verbose("Trying to set broad to %s = %s\n",VNUMBROADCAST,inet_ntoa(sin->sin_addr));
  290.  
  291. if (ioctl(sk,SIOCSIFBRDADDR, (caddr_t) &IFR) == -1) 
  292.    {
  293.    CfLog(cferror,"Permission to reconfigure broadcast denied.\n","ioctl");
  294.    return;
  295.    } 
  296.  
  297. if ((char *) sin->sin_addr.s_addr == NULL)
  298.    {
  299.    CfLog(cferror,"No broadcast address on socket after configuration!!\n","");
  300.    }
  301. else
  302.    {
  303.    sprintf(OUTPUT,"Set Broadcast address to: %s\n",inet_ntoa(sin->sin_addr));
  304.    CfLog(cfinform,OUTPUT,"");
  305.    }
  306. }
  307.  
  308. /*****************************************************/
  309.  
  310. GetBroadcastAddr(ipaddr,vifdev,vnetmask,vbroadcast)
  311.  
  312. char *ipaddr,*vifdev,*vnetmask,*vbroadcast;
  313.  
  314. { unsigned int na,nb,nc,nd;
  315.   unsigned int ia,ib,ic,id;
  316.   unsigned int ba,bb,bc,bd;
  317.   unsigned netmask,ip,broadcast;
  318.  
  319. sscanf(vnetmask,"%u.%u.%u.%u",&na,&nb,&nc,&nd);
  320.  
  321. netmask = nd + 256*nc + 256*256*nb + 256*256*256*na;
  322.  
  323. sscanf(ipaddr,"%u.%u.%u.%u",&ia,&ib,&ic,&id);
  324.  
  325. ip = id + 256*ic + 256*256*ib + 256*256*256*ia;
  326.  
  327. if (strcmp(vbroadcast,"zero") == 0)
  328.    {
  329.    broadcast = ip & netmask;
  330.    }
  331. else if (strcmp(vbroadcast,"one") == 0)
  332.    {
  333.    broadcast = ip | (~netmask);
  334.    }
  335. else
  336.    {
  337.    return;
  338.    }
  339.  
  340. ba = broadcast / (256 * 256 * 256);
  341. bb = (broadcast / (256 * 256)) % 256;
  342. bc = broadcast / (256) % 256;
  343. bd = broadcast % 256;
  344. sprintf(VNUMBROADCAST,"%u.%u.%u.%u",ba,bb,bc,bd);
  345. }
  346.  
  347. /****************************************************************/
  348. /*                                                              */
  349. /* Routing Tables:                                              */
  350. /*                                                              */
  351. /* To check that we have at least one static route entry to     */
  352. /* the nearest gateway -- i.e. the wildcard entry for "default" */
  353. /* we need some way of accessing the routing tables. There is   */
  354. /* no elegant way of doing this, alas.                          */
  355. /*                                                              */
  356. /****************************************************************/
  357.  
  358. SetDefaultRoute()
  359.  
  360. { int sk, defaultokay = 1;
  361.   struct sockaddr_in sindst,singw;
  362.  
  363. # ifdef HAVE_ORTENTRY
  364.    struct ortentry route;
  365. # else if HAVE_RTENTRY
  366.    struct rtentry route;
  367. # endif
  368.  
  369.   FILE *pp;
  370.  
  371. Verbose("Looking at default route...\n");
  372.   
  373. if (getuid() != 0)                            
  374.    {
  375.    sprintf(OUTPUT,"Only root can set a default route.");
  376.    CfLog(cfinform,OUTPUT,"");
  377.    return;
  378.    }
  379.  
  380. if (VDEFAULTROUTE[0] == '\0')
  381.    {
  382.    Debug("cfengine: No default route is defined. Ignoring the routing tables.\n");
  383.    return;
  384.    }
  385.  
  386. if ((pp = cfpopen(VNETSTAT[VSYSTEMHARDCLASS],"r")) == NULL)
  387.    {
  388.    sprintf(OUTPUT,"Failed to open pipe from %s\n",VNETSTAT[VSYSTEMHARDCLASS]);
  389.    CfLog(cferror,OUTPUT,"popen");
  390.    return;
  391.    }
  392.  
  393. while (!feof(pp))
  394.    {
  395.    ReadLine(VBUFF,bufsize,pp);
  396.    
  397.    if (strncmp(VBUFF,"default",7) == 0)
  398.       {
  399.       if (strstr(VBUFF,VDEFAULTROUTE))
  400.          {
  401.      Verbose("cfengine: default route is already set to %s\n",VDEFAULTROUTE);
  402.          defaultokay = 1;
  403.          break;
  404.          }
  405.       else
  406.          {
  407.          CfLog(cferror,"The default packet-route is incorrectly set\n","");
  408.          CfLog(cferror,"Please correct this manually using route(1).\n","");
  409.          break;
  410.          }
  411.       }
  412.    defaultokay = 0;
  413.    }
  414.  
  415. cfpclose(pp);
  416.  
  417. if (defaultokay)
  418.    {
  419.    return;
  420.    }
  421.  
  422. # if defined HAVE_RTENTRY || defined HAVE_ORTENTRY
  423.  
  424. if ((sk = socket(AF_INET,SOCK_RAW,cfproto)) == -1)
  425.    {
  426.    if ( VSYSTEMHARDCLASS == linuxx )
  427.       {
  428.       Debug ("No raw socket protocol for linux\n");
  429.       return;
  430.       }
  431.    
  432.    printf("System class %s\n",CLASSTEXT[VSYSTEMHARDCLASS]);
  433.    perror("cfengine: socket");
  434.    FatalError("Error in SetDefaultRoute()");
  435.    }
  436.  
  437. sindst.sin_family = AF_INET;
  438. singw.sin_family = AF_INET;
  439.  
  440. sindst.sin_addr.s_addr = INADDR_ANY;
  441. singw.sin_addr.s_addr = inet_addr(VDEFAULTROUTE);
  442.  
  443. route.rt_dst = *(struct sockaddr *)&sindst;      /* This disgusting method is necessary */
  444. route.rt_gateway = *(struct sockaddr *)&singw;
  445. route.rt_flags = RTF_GATEWAY;
  446.  
  447. if (! DONTDO)
  448.    {
  449.    if (ioctl(sk,SIOCADDRT, (caddr_t) &route) == -1)   /* Get the device status flags */
  450.       {
  451.       CfLog(cferror,"","ioctl SIOCADDRT:");
  452.       FatalError("Software error: set default route");
  453.       }
  454.  
  455.    CfLog(cferror,"The routing table did not contain a default route.\n","");
  456.    sprintf(OUTPUT,"I'm setting it to %s\n",VDEFAULTROUTE);
  457.    CfLog(cferror,OUTPUT,"");
  458.    }
  459.  
  460. # else if
  461.  
  462. /* Socket routing - don't really know how to do this yet */ 
  463.  
  464. Verbose("Sorry don't know how to do routing on this platform\n");
  465.  
  466. # endif
  467. }
  468.  
  469. #else /* NT */
  470.  
  471. IfConf (vifdev,vnetmask,vbroadcast)
  472.  
  473. char *vifdev,*vnetmask, *vbroadcast;
  474.  
  475. {
  476. Verbose("Network configuration is not implemented on this OS\n");
  477. }
  478.  
  479. SetDefaultRoute()
  480.  
  481. {
  482. Verbose("Setting default route is not implemented on this OS\n"); 
  483. }
  484.  
  485. #endif
  486.